/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cc.uah.es.snomedctsubsetextractor;

import edu.uci.ics.jung.algorithms.layout.CircleLayout;
import edu.uci.ics.jung.algorithms.layout.Layout;
import edu.uci.ics.jung.algorithms.layout.TreeLayout;
import edu.uci.ics.jung.algorithms.shortestpath.MinimumSpanningForest2;
import edu.uci.ics.jung.graph.DelegateForest;
import edu.uci.ics.jung.graph.DelegateTree;
import edu.uci.ics.jung.graph.Forest;
import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.visualization.VisualizationViewer;
import edu.uci.ics.jung.visualization.control.CrossoverScalingControl;
import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse;
import edu.uci.ics.jung.visualization.control.ModalGraphMouse;
import edu.uci.ics.jung.visualization.control.ScalingControl;
import edu.uci.ics.jung.visualization.decorators.EdgeShape;
import edu.uci.ics.jung.visualization.decorators.EllipseVertexShapeTransformer;
import edu.uci.ics.jung.visualization.decorators.PickableEdgePaintTransformer;
import edu.uci.ics.jung.visualization.decorators.PickableVertexPaintTransformer;
import edu.uci.ics.jung.visualization.decorators.ToStringLabeller;
import edu.uci.ics.jung.visualization.picking.MultiPickedState;
import edu.uci.ics.jung.visualization.picking.PickedState;
import edu.uci.ics.jung.visualization.subLayout.TreeCollapser;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Collection;
import java.util.HashSet;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import org.apache.commons.collections15.Transformer;
import org.apache.commons.collections15.functors.ConstantTransformer;

/**
 *
 * @author Luis
 */
public class SimpleGraphView {

    private Graph<Integer, String> g;
    /**
     * the graph
     */
    Forest<Integer, String> graphForest;

    public SimpleGraphView(Graph<Integer, String> gv) {
        this.g = gv;
    }

    public void printInteractiveGraph() {
        // Layout<V, E>, VisualizationComponent<V,E>
        Layout<Integer, String> layout = new CircleLayout(this.g);

        layout.setSize(new Dimension(300, 300));
        VisualizationViewer<Integer, String> vv = new VisualizationViewer<Integer, String>(layout);
        vv.setPreferredSize(new Dimension(350, 350));
        // Show vertex and edge labels
        vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller());
        vv.getRenderContext().setEdgeLabelTransformer(new ToStringLabeller());
        // Create a graph mouse and add it to the visualization component
        DefaultModalGraphMouse gm = new DefaultModalGraphMouse();
        gm.setMode(ModalGraphMouse.Mode.TRANSFORMING);
        vv.setGraphMouse(gm);
        JFrame frame = new JFrame("Interactive Graph View 1");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(vv);
        frame.pack();
        frame.setVisible(true);
    }

    public void printTree() {

        /**
         * the visual component and renderer for the graph
         */
        final VisualizationViewer<Integer, String> vv;
        final TreeLayout<Integer, String> treeLayout;

        MinimumSpanningForest2<Integer, String> prim =
                new MinimumSpanningForest2<Integer, String>(g,
                new DelegateForest<Integer, String>(), DelegateTree.<Integer, String>getFactory(),
                new ConstantTransformer(1.0));

        graphForest = prim.getForest();

        treeLayout = new TreeLayout<Integer, String>(graphForest);
        final TreeCollapser collapser = new TreeCollapser();

        vv = new VisualizationViewer<Integer, String>(treeLayout, new Dimension(600, 600));
        vv.setBackground(Color.white);

        // share one PickedState between the two views
        PickedState<Integer> ps = new MultiPickedState<Integer>();
        vv.setPickedVertexState(ps);

        PickedState<String> pes = new MultiPickedState<String>();
        vv.setPickedEdgeState(pes);

        // set an edge paint function that will show picking for edges
        vv.getRenderContext().setEdgeDrawPaintTransformer(new PickableEdgePaintTransformer<String>(vv.getPickedEdgeState(), Color.black, Color.red));
        vv.getRenderContext().setVertexFillPaintTransformer(new PickableVertexPaintTransformer<Integer>(vv.getPickedVertexState(),
                Color.GREEN, Color.yellow));

        vv.getRenderContext().setEdgeShapeTransformer(new EdgeShape.Line());
        vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller());
        //vv.getRenderContext().setVertexFillPaintTransformer(new ConstantTransformer(Color.GREEN));
        vv.getRenderContext().setVertexShapeTransformer(new ClusterVertexShapeFunction());

        // add a listener for ToolTips
        vv.setVertexToolTipTransformer(new ToStringLabeller());
        vv.getRenderContext().setArrowFillPaintTransformer(new ConstantTransformer(Color.lightGray));

        DefaultModalGraphMouse gm = new DefaultModalGraphMouse();
        //gm.setMode(ModalGraphMouse.Mode.TRANSFORMING);
        //gm.setMode(ModalGraphMouse.Mode.PICKING);
        vv.setGraphMouse(gm);

        JFrame frame = new JFrame("Interactive Tree Graph View 1");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // create zoom buttons for scaling the transformer that is
        // shared between the two models.
        final ScalingControl scaler = new CrossoverScalingControl();

        vv.scaleToLayout(scaler);

        JButton plus = new JButton("+");
        plus.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                scaler.scale(vv, 1.1f, vv.getCenter());
            }
        });
        JButton minus = new JButton("-");
        minus.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                scaler.scale(vv, 1 / 1.1f, vv.getCenter());
            }
        });

        JButton collapse = new JButton("Collapse");
        collapse.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                Collection picked = new HashSet(vv.getPickedVertexState().getPicked());
                if (picked.size() == 1) {
                    Object root = picked.iterator().next();
                    Forest inGraph = (Forest) treeLayout.getGraph();

                    try {
                        collapser.collapse(vv.getGraphLayout(), inGraph, root);
                    } catch (InstantiationException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    } catch (IllegalAccessException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    }

                    vv.getPickedVertexState().clear();
                    vv.repaint();
                }
            }
        });

        JButton expand = new JButton("Expand");
        expand.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                Collection picked = vv.getPickedVertexState().getPicked();
                for (Object v : picked) {
                    if (v instanceof Forest) {
                        Forest inGraph = (Forest) treeLayout.getGraph();
                        collapser.expand(inGraph, (Forest) v);
                    }
                    vv.getPickedVertexState().clear();
                    vv.repaint();
                }
            }
        });

        JPanel zoomPanel = new JPanel(new GridLayout(1, 2));
        zoomPanel.setBorder(BorderFactory.createTitledBorder("Zoom"));

        JPanel modePanel = new JPanel();
        modePanel.setBorder(BorderFactory.createTitledBorder("Mouse Mode"));
        gm.getModeComboBox().addItemListener(gm.getModeListener());
        modePanel.add(gm.getModeComboBox());

        JPanel controls = new JPanel();
        zoomPanel.add(plus);
        zoomPanel.add(minus);
        controls.add(zoomPanel);
        controls.add(modePanel);
        controls.add(collapse);
        controls.add(expand);

        frame.getContentPane().add(controls, BorderLayout.SOUTH);


        frame.getContentPane().add(vv);
        frame.pack();
        frame.setVisible(true);


    }

  
   /**
     * a demo class that will create a vertex shape that is either a
     * polygon or star. The number of sides corresponds to the number
     * of vertices that were collapsed into the vertex represented by
     * this shape.
     *
     * @author Tom Nelson
     *
     * @param <V>
     */
    class ClusterVertexShapeFunction<V> extends EllipseVertexShapeTransformer<V>
{

        ClusterVertexShapeFunction() {
            setSizeTransformer(new ClusterVertexSizeFunction<V>(20));
        }
        @SuppressWarnings("unchecked")
		@Override
        public Shape transform(V v) {
            if(v instanceof Graph) {
                int size = ((Graph)v).getVertexCount();
                if (size < 8) {
                    int sides = Math.max(size, 3);
                    return factory.getRegularPolygon(v, sides);
                }
                else {
                    return factory.getRegularStar(v, size);
                }
            }
            return super.transform(v);
        }
    }

    /**
     * A demo class that will make vertices larger if they represent
     * a collapsed collection of original vertices
     * @author Tom Nelson
     *
     * @param <V>
     */
    class ClusterVertexSizeFunction<V> implements Transformer<V,Integer> {
    	int size;
        public ClusterVertexSizeFunction(Integer size) {
            this.size = size;
        }

        public Integer transform(V v) {
            if(v instanceof Graph) {
                return 30;
            }
            return size;
        }
    }
}
